home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
assemblr
/
library
/
sampler0
/
senddisk.asm
< prev
next >
Wrap
Assembly Source File
|
1988-11-08
|
17KB
|
541 lines
;********* S E N D D I S K . A S M *******************************************
; A disk duplication utility to allow all sectors (including boot)
; of a floppy disk to be transmitted via a temporary file over a
; modem and replaced on another floppy disk. With this utility,
; you should be able to distribute the IBM PC-DOS 4.0 fix disks
; with the SBBS system. The temporary file is 368,640 bytes long
; for a 360k diskette and twice that for a 720k diskette. This is long,
; but length should compress nicely using pkarc or equivalent.
; The .exe version of this file needs to be included in the .ARC
; file distributed to enable recreation of the disk.
;
; This program will allow a BOOTABLE disk to be transmitted via a
; modem and recreated at another location.
;
; created 2 November 1988
; Jim Offenbecher, Software Librarian, Huntsville PC Users Group
; 13920 Creely Drive SW
; Huntsville, AL 35803
; Tel: [H] (205) 882-3205
; [W] (205) 881-5741
;
; modified to: 1. Allow 720k disk usage with message showing type.
; 2. Check file length prior to disk write.
; 3. Comment the source code.
; 4 November 1988 - jko (per conversation with IBM SBBS)
;
; This program including source code is hereby placed in the
; Public Domain for all to use. This program including source
; code may be freely distributed provided that no fee is charged
; for it or it's distribution. Feel free to modify it providing
; original credits are retained - it is quick and dirty to allow
; early distribution of the DOS 4.0 fixes...
; yes I know the error exits don't reset the stack on exit...
; assemble with MASM 5.0 or above - no macros or libraries needed.
.model small
.data
cr equ 0dh
lf equ 0ah
secsiz equ 512
sectrk equ 9
;track count for 3.5" 720k disks
trks7 equ 80
;track count for 5.25" 360k disks
trks equ 40
sides equ 2
trklen equ secsiz * sectrk
; number of clusters to check for when IDing the floppy
; if it's more than this, and the FAT ID is 0F9h, then it's a
; 5.25" 1.2 Meg and not a 720k 3.5" diskette...
clustchk equ 750
signon db ' SENDDISK.EXE',cr,lf
db cr,lf
db 'A Utility program to allow the IBM SBBS to',cr,lf
db 'distribute the patches for IBM Dos 4.0 via',cr,lf
db 'file mode. This Program captures the entire',cr,lf
db 'disk into a single file and/or recreates the',cr,lf
db 'disk from the file. It requires a disk which',cr,lf
db 'has been formatted to 360k (9 secs per track)',cr,lf
db 'or to 720k (80 tracks-9 secs per track- 3.5")',cr,lf
db 'in the A: or B: drive. It is quick and dirty,',cr,lf
db 'written in assembly, and is hereby placed in',cr,lf
db 'the public domain for all to use.',cr,lf
db cr,lf
db ' by Jim Offenbecher',cr,lf
db ' SSS Computer Center Inc.',cr,lf
db ' Huntsville, Alabama',cr,lf
db 'Software Librarian- Huntsville PC Users Group (P1239 AL)',cr,lf
db cr,lf
dirask db cr,lf,'Do you want to:',cr,lf
db ' 1. Read a floppy disk into a file on hard disk',cr,lf
db ' 2. Write a hard disk file onto a floppy disk',cr,lf
db ' Enter your choice (1-2)->','$'
askerr db cr,lf,'Must be a 1 or 2 only',cr,lf,'$'
as2err db cr,lf,'Must be an A or B only',cr,lf,'$'
askdsk db cr,lf,'Enter Floppy Disk Drive Designation (A-B)->','$'
typ360 db cr,lf,'Diskette is 360k 5.25 inch',cr,lf,'$'
typ720 db cr,lf,'Diskette is 720k 3.5 inch',cr,lf,'$'
askfil db cr,lf,'Enter Hard Disk File Name ->','$'
rerr001 db cr,lf,'Error Reading Floppy Disk',cr,lf,'$'
werr001 db cr,lf,'Error Writing Floppy Disk',cr,lf,'$'
serr001 db cr,lf,'File Size does NOT match disk type',cr,lf,'$'
newlin db cr,lf,'$'
nofile db cr,lf,'File Not Found',cr,lf,'$'
badpath db cr,lf,'Invalid Path',cr,lf,'$'
nohand db cr,lf,'No Handle Available',cr,lf,'$'
accden db cr,lf,'Access to File Denied',cr,lf,'$'
gopnerr db cr,lf,'Error Opening File',cr,lf,'$'
gmaker db cr,lf,'Error Creating File',cr,lf,'$'
rfiler db cr,lf,'Error Reading File',cr,lf,'$'
wfiler db cr,lf,'Error Writing File',cr,lf,'$'
closerr db cr,lf,'Error Closing File',cr,lf,'$'
fwtok db cr,lf,'Disk Capture Successful',cr,lf,'$'
dwtok db cr,lf,'Disk Re-Creation Successful',cr,lf,'$'
dotmsg db '.$'
; storage for temporary variables
;file name input buffer
bufinp db 40 ;max length of buffer
chrcnt db 0
; 1234567890123456789012345678901234567890
filsto db ' '
; ascii storage for the floppy drive involved
drivasc db 'A'
; binary storage for the floppy drive involved
dskbin db 1
; disk type (number of tracks)
dsktyp dw 80
;current sector storage for reading and writing floppy disk
cursec dw 0
; storage for the file handle assigned to the temp file
handle dw 0
; buffer for a single track of data...
bugbuff db sectrk+1 dup (secsiz dup (?))
; executable code begins here...
.code
mov ax,@data ;MASM 5.0+ find data segment
mov ds,ax ;set up data segment
mov es,ax ;set up extended segment too
restart:
mov dx,offset signon
mov ah,9
int 21h ;sign on the system
mov ah,1
int 21h ;get a single character
cmp al,'1' ;check for make file condition
jz makfil ;go make a file if so
cmp al,'2' ;check for make disk condition
jz makdsk ;go make a disk if a 2
mov dx,offset askerr
mov ah,9 ;print error if not 1 or 2
int 21h
jmp restart ;and ask again
;this module creates a file on the hard disk from all sectors on the
;specified floppy drive. Drive type is checked to determine correct
;number of sectors to read.
makfil:
call getdisk ;find out which floppy to use
call getfile ;and the file name to use too
call makefile ; make the file
jc exit ;exit if error
mov cx,0 ;start at sector zero
mov cursec,cx
mov cx,dsktyp ;get # tracks this type
; copy a single track from the floppy to a file, looping till all tracks done
fillop:
push cx ;save track counter
mov dx,offset dotmsg;tell user another track
mov ah,9
int 21h
call readdisk ;go read track into buffer
call writfile ;write buffer out to file
mov cx,cursec ;get starting sector read last time
add cx,9
mov cursec,cx ;bump the starting sector for next loop
pop cx ;get track counter back
dec cx ;one less track to do
jnz fillop ;loop till all tracks done...
; all done writing the file, so bye-bye
call closfile ;close the new file
mov dx,offset fwtok
jmp errexit ;tell user OK, and leave the program
; this module writes all sectors on a floppy disk from data in a
; file on the hard disk. The floppy must be formatted, and the file
; length must match the format of the floppy disk.
makdsk:
call getdisk ;find out which floppy to use
call getfile ;and which file to write to it
call openfile ;open the file using handles
jc exit ;abort if can't open
call lenchk ;check length and abort if wrong
mov cx,0 ;initialize the sector to write to
mov cursec,cx
mov cx,dsktyp ;and get the track count from storage
; this module reads one track's worth of data from the file and
; writes it out to the floppy, looping until 'dsktyp' tracks are written
fil2lop:
push cx ;save the track counter on stack
mov dx,offset dotmsg ;tell him we're working
mov ah,9
int 21h
call readfile ;get one tracks data from file
call writdisk ;put it on the floppy
mov cx,cursec ;get the old starting sector written
add cx,9 ;bump it one track's worth
mov cursec,cx ;and save it for next loop
pop cx ;get track counter back
dec cx ;one less track to do
jnz fil2lop ;loop till all tracks done...
;all done writing the floppy drive now...
call closfile ;close the file
mov dx,offset dwtok
jmp errexit ;tell user OK, and exit the program
;common exit point for errors... prints string at DS:DX and then exits...
errexit:
mov ah,9
int 21h
exit:
mov ah,4ch
int 21h
; this module prompts the operator for the floppy drive to use, only A and
; B are acceptable answers. It then checks the type of media involved using
; the FAT Descriptor for 360k drives, and a combination of the FAT Descriptor
; and the cluster count for 720k drives. The correct number of 9 sectored
; tracks is stored for later loop usage.
getdisk:
mov dx,offset askdsk
mov ah,9
int 21h ;ask the question
mov ah,1
int 21h ;get the answer
and al,05fh ;make lower case
cmp al,3
jz exit ;exit on control-c
cmp al,27
jz exit ;or on escape char
cmp al,'A' ;was it an 'A'???
jnz gd002
;process drive A request
mov drivasc,al ;save for later use
sub al,41h ;convert to binary
mov dskbin,al ;save it too
jmp gdret ;jump around the B check and error for
;common return
;it wasn't an A so check for a B
gd002:
cmp al,'B'
jnz gd003 ;not B either - then must be wrong
mov drivasc,al ;save the B for later use
sub al,41h ;convert to binary
mov dskbin,al ;save it too
jmp gdret
;here if not A or B - must be error...
gd003: ;here if in error
mov dx,offset as2err
mov ah,9
int 21h ;tell him A or B only
jmp getdisk ;ask again...
;here with al containing binary drive value...0=A, 1=B
gdret:
inc al ;convert to base 1 for absolute call
mov dl,al ;put in DL for absolute call
mov ah,1ch ;put the GET FAT function in AH
push ds ;save from int 21 function
int 21h
jnc gdret1 ;got a good fat description
jmp readerr ;couldn't get a good FAT description
;here if got good fat function call - note: DS has changed.....
gdret1:
mov al,Byte Ptr[bx] ;get the Media Descriptor Byte...
pop ds ;restore Data Segment to ours...
cmp al,0fdh ;check for 9 sector 5.25 inch disk
jnz chk720 ;no, check for the 720k...
mov ax,80 ;360k disk has 40 trks, 2 sides, for tot of 80
mov dsktyp,ax ;save in storage for later loop
mov dx,offset typ360
mov ah,9
int 21h ;tell user it's a 360
jmp dskgood ;go to common exit point...
;here if wasn't a 360k drive in the selected drive...
chk720:
cmp al,0f9h ;check for 3.5 inch disk...(maybe 1.2 Meg)??
jnz readerr ;if not 0fdh or 0f9h then must be wrong type
; both the 3.5" 720k and the 1.2m 5.25 have an f9 Fat descriptor -
; use the tot clusters to insure it's a 720k...
cmp dx,clustchk ;check for 720k
jnc readerr ;error if it's too many
mov ax,160 ;track count on 3.5 inch disk
mov dsktyp,ax ;save the total tracks for later looping use
; now have good drive type entered, and know correct number of tracks to use
dskgood:
mov dx,offset newlin
mov ah,9
int 21h ;just start a new line for clarity...
ret
; this module prompts for and inputs a file name to use via the buffered
; input routine. It also terminates the input with a zero byte for the
; file handle routines to come later...
getfile:
mov dx,offset askfil
mov ah,9
int 21h ;show user what we want...
mov ah,0ah ;buffered input for file name...
mov dx,offset bufinp
int 21h ;get an input from him..
mov al,chrcnt ;get character count he entered
cmp al,0 ;nothing means exit...
jnz gfl01 ;he did something...
jmp exit
;operator entered a response other than enter key...
gfl01:
mov ah,0 ;clear hi byte of AX
mov di,offset filsto;set offset to 1st character entered
add di,ax ;add the number of chars entered
mov byte ptr[di],0 ;put a zero terminator there
mov dx,offset newlin;clear the line for clarity...
mov ah,9
int 21h
ret
; this module opens the file using the handle function...
openfile:
mov ah,3dh ;function to open file handle
mov al,0 ;read only mode - careful...
mov dx,offset filsto;point to ASCIIZ name...
int 21h ;go try to open...
jnc openok ;if carry not set, then ok...
;here if error opening file... check sequentially for errors...
mov dx,offset nofile
cmp al,2 ;error 2 is no file found
jz openerr
mov dx,offset badpath
cmp al,3 ;error 3 is can't find path
jz openerr
mov dx,offset nohand
cmp al,4 ;error 4 is no handle available
jz openerr
mov dx,offset accden
cmp al,5 ;error 5 is Access Denied
jz openerr
mov dx,offset gopnerr
;use general error if not above...
openerr:
jmp errexit ;go print the error and quit...
;here if file opened ok...
openok:
mov handle,ax ;save handle for later use.
ret
;tell operator we had an error reading file and then exit..
readerr:
mov dx,offset rerr001
jmp errexit
; this module creates a new file when reading in a floppy disk
makefile:
mov ah,3ch ;function in AH
mov cx,0 ;attributes set to none
mov dx,offset filsto;point to ASCIIZ string inputted
int 21h ;go try to make it
jnc makeok ;carry not set - then OK - it's made
mov dx,offset badpath
cmp al,3 ;error 3 is can't find path
jz makerr
mov dx,offset nohand
cmp al,4 ;error 4 is no handle available
jz makerr
mov dx,offset accden
cmp al,5 ;error 5 is access denied
jz makerr
mov dx,offset gmaker
;use general error if not above...
makerr:
jmp errexit ;print the error for user and exit
;here if file was created OK
makeok:
mov handle,ax ;save handle for later writes...
ret
;this module closes the file and updates the directory
closfile:
mov ah,3eh ;function to close in AH
mov bx,handle ;get the saved handle
int 21h ;go close it
jnc closok ;branch if no error ocurred
;here if error closing file
mov dx,offset closerr
jmp errexit ;print the error and exit
;here if closed OK
closok:
ret
; this module reads one tracks worth of data (9 sectors) into the buffer.
; the file pointer is left for DOS to handle, we only do a sequential read.
readfile:
mov ah,3fh ;function in AH
mov bx,handle ;handle in BX
mov dx,offset bugbuff;point to the buffer to use
mov cx,trklen ;number of bytes to read in CX
int 21h ;go read the file
jnc readok ;skip error if none ocurred
rfiler2:
mov dx,offset rfiler
jmp errexit ;tell him an error and exit
;here if no error ocurred, however, make sure we didn't run out of bytes...
readok:
cmp ax,cx ;see if we read all we wanted...
jnz rfiler2 ;error if short read...
ret
; this routine writes one track's worth of data from the buffer to the file
; the file pointer is left for DOS to handle, we only do a sequential write.
writfile:
mov ah,40h ;function in AH
mov bx,handle ;handle in BX
mov dx,offset bugbuff;point to the buffer to use
mov cx,trklen ;number of bytes to write in CX
int 21h ;go write it
jnc writok ;skip error if none ocurred
;here if DOS reported an error
wfiler2:
call closfile ;don't leave lost clusters
mov dx,offset wfiler
jmp errexit ;tell user we can't write and exit
;here if no error ocurred, however, make sure we wrote the whole buffer...
writok:
cmp ax,cx ;check to see complete write
jnz wfiler2 ;error if not
ret ;else all is ok
; this module reads one track's worth of data from the floppy disk
readdisk:
mov al,dskbin ;get the disk to use
mov cx,9 ;nine sectors per track
mov dx,cursec ;where to start
mov bx,offset bugbuff;where to put data
int 25h ;go do it
pop cx ;clean up stack from int 25h (the flags)
jnc dredok ;skip the error if ok
jmp readerr ;else tell user and exit
;here if read the track ok
dredok:
ret
; this module writes one track's worth of data to the floppy disk
writdisk:
mov al,dskbin ;get the disk to use
mov cx,9 ;write the whole nine sectors
mov dx,cursec ;where to start
mov bx,offset bugbuff;where to get data from
int 26h ;go do it
pop cx ;clean up stack from int 25h (the flags)
jnc dwitok ;skip the error if ok
jmp writerr ;else tell user and exit
;here if wrote the whole track
dwitok:
ret
;here if an error writing a track to floppy disk
writerr:
mov dx,offset werr001
jmp errexit
; check the length of the file to see if it came from the same type
; disk drive - 360k disks return DX=0005 and AX=A000 while
; 720k drives return DX=000B and AX=4000... error exit if no match..
lenchk:
mov ax,4202h ;LSEEK ref EOF
mov bx,handle ;file handle to use
mov cx,0 ;cx and dx set the offset
mov dx,cx ;offset 0 from end
int 21h ;go move the DOS pointer
push dx ;save the pointer (DX:AX) on stack for rewind
push ax
mov ax,4200h ;LSEEK ref beginning
mov bx,handle ;same file
mov cx,0 ;same offset
mov dx,cx ;offset 0 from beginning
int 21h ;reset pointer to beginning
pop ax ;get the length back from the stack
pop dx
; now have file length in DX:AX and pointer back at beginning of file...
mov cx,dsktyp ;get # tracks in CX
mov si,5 ;set to 360k first
mov di,0a000h
cmp cx,80 ;check for 360k track count
jz chkit ;ok, then skip the set to 720k value
mov si,0bh ;set comparators to 720k standard
mov di,04000h
chkit:
; now compare DX with SI and AX with DI - if they dont both match, file
; is the wrong size...
cmp dx,si ;check hi words first
jnz sizerr ;error if not equal
cmp ax,di ;check lo words too
jnz sizerr ;error if not equal
ret ;ok, file is right length
; here if wrong size file - tell user and abort program.
sizerr:
mov dx,offset serr001
jmp errexit
;thats all folks......
end